package com.hp.util;

import com.hp.entity.LoginInfor;
import com.hp.service.UserService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

@Aspect
@Component
public class MyAspect {
    @Resource
    private UserService userService;
    //配置切入点
    @Pointcut("execution(* com.hp.controller.*.*(..))")
    private void controllerAspect(){

    }//定义一个切入点
    //在和aroundAdvice结合的时候,这个方法一定要加上这个ProceedingJoinPoint类型的参数
    @Around(value = "controllerAspect()")
    public Object aroundTest(ProceedingJoinPoint pjp) throws Throwable {
        return this.show(pjp);
    }

    private Object show(ProceedingJoinPoint pjp) throws Throwable{
        //常见日志实体对象
        LoginInfor log = new LoginInfor();
        //获取登录用户账户,RequestContextHolder是使用spring获取serlvet的方法
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        log.setUser_id(request.getSession().toString() == null ?"" :request.getSession().toString());
        //获取系统时间
       // String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        log.setCreate_datetime(new Date());
        //获取系统ip
        String ip = IPUtil.getIPAddress(request);
        log.setLogin_ip(ip);
        //方法通知前获取时间
        long start = System.currentTimeMillis();
        // 拦截的实体类，就是当前正在执行的controller
        Object target = pjp.getTarget();
        // 拦截的方法名称。当前正在执行的方法
        String methodName = pjp.getSignature().getName();
        // 拦截的方法参数
        Object[] args = pjp.getArgs();
        // 拦截的放参数类型
        Signature sig = pjp.getSignature();

        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        MethodSignature msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod().getParameterTypes();
        Object object = null;
        // 获得被拦截的方法
        Method method = null;
        try {
            method = target.getClass().getMethod(methodName, parameterTypes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (null != method) {
            // 判断是否包含自定义的注解，说明一下这里的Logblog就是我自己自定义的注解
            if (method.isAnnotationPresent(Logblog.class)) {
                Logblog sysLog = method.getAnnotation(Logblog.class);
                log.setModule(sysLog.module());
                log.setMethod(sysLog.method());
                try {
                    object = pjp.proceed();
                    long end = System.currentTimeMillis();
                    //将计算好的时间保存在实体中
                    log.setRESPONSE_DATE("" + (end - start));
                    log.setCOMMIT("执行成功！");
                    //保存进数据库
                    userService.saveLog(log);
                } catch (Throwable e) {
                    long end = System.currentTimeMillis();
                    log.setRESPONSE_DATE("" + (end - start));
                    log.setCOMMIT("执行失败");
                    userService.saveLog(log);
                }
            } else {//没有包含注解
                object = pjp.proceed();
            }
        } else { //不需要拦截直接执行
            object = pjp.proceed();
        }
        return object;
    }
    public MyAspect() {
        System.out.println("MyAspect ----------------- 构造");
    }
}
